/*************************************************************************/
/** Copyright.															**/
/** FileName: TextPaintPanel.cpp										**/
/** Author: Polarix														**/
/** Description: Used for paint and preview pixelated text.				**/
/*************************************************************************/
//=======================================================================//
//= Include files.													    =//
//=======================================================================//
#include "PicturePaintCtrl.h"

//=======================================================================//
//= Function define.										            =//
//=======================================================================//
BEGIN_EVENT_TABLE(PicturePaintCtrl, wxLCDBase)
	EVT_MOUSE_EVENTS(PicturePaintCtrl::OnMouseEvent)
END_EVENT_TABLE()

PicturePaintCtrl::PicturePaintCtrl(wxWindow *pclsParent, wxWindowID iWinID, const wxSize& clsSizeInPixel):
wxLCDBase(pclsParent, iWinID, wxDefaultPosition, clsSizeInPixel, wxT("Image Paint Coltrol"))
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	m_clsPixelLColour = (*wxBLACK);
	m_clsPixelHColour = (*wxWHITE);
	SetPixelUnitSize(wxSize(5, 5));
	SetBorderWidth(0);
	SetGridVisibled(true);
	SetGridColor(wxColour(127, 127, 127));
}

PicturePaintCtrl::~PicturePaintCtrl(void)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
}

void PicturePaintCtrl::SetPanelColour(const wxColour& clsPanelColour, bool bRefreshNow)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	// Replace old panel color.
	ReplaceColour(m_clsPixelLColour, clsPanelColour);
	// Set new panel color.
	m_clsPixelLColour = clsPanelColour;
	// Refresh display.
	if(true == bRefreshNow)
	{
		RefreshDisplay();
	}
}

void PicturePaintCtrl::SetPixelColour(const wxColour& clsPixelColour, bool bRefreshNow)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	// Replace old pixel color.
	ReplaceColour(m_clsPixelHColour, clsPixelColour);
	// Set new pixel color.
	m_clsPixelHColour = clsPixelColour;
	// Refresh display.
	if(true == bRefreshNow)
	{
		RefreshDisplay();
	}
}

int PicturePaintCtrl::GetPixel(const int iPosX, const int iPosY)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	int				iReturn;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(WX_LCD_PIX_RGB(GetPixelUnitColor(iPosX, iPosY)) == WX_LCD_PIX_RGB(m_clsPixelHColour.GetRGBA()))
	{
		iReturn = 1;
	}
	else
	{
		iReturn = 0;
	}

	return iReturn;
}

void PicturePaintCtrl::SetPixel(const int iPosX, const int iPosY, const int iValue)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(1 == iValue)
	{
		SetPixelUnitColor(iPosX, iPosY, m_clsPixelHColour);
	}
	else
	{
		SetPixelUnitColor(iPosX, iPosY, m_clsPixelLColour);
	}
}

void PicturePaintCtrl::CleanScreen(void)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	FillColour(m_clsPixelLColour);
}

void PicturePaintCtrl::OnMouseEvent(wxMouseEvent& clsEvent)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxSize				clsPixelUnitSize = GetPixelUnitSize();
    int					iPosX = clsEvent.GetPosition().x;
    int					iPosY = clsEvent.GetPosition().y;
    int					iPixelPosX = (iPosX-GetBorderWidth())/clsPixelUnitSize.GetWidth();
    int					iPixelPosY = (iPosY-GetBorderWidth())/clsPixelUnitSize.GetHeight();

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	if(true == clsEvent.LeftDown())
	{
		DrawPixel(iPixelPosX, iPixelPosY, m_clsPixelHColour);
	}
	if(true == clsEvent.RightDown())
	{
		DrawPixel(iPixelPosX, iPixelPosY, m_clsPixelLColour);
	}

	if(true == clsEvent.Moving())
	{
		if(true == clsEvent.LeftIsDown())
		{
			DrawPixel(iPixelPosX, iPixelPosY, m_clsPixelHColour);
		}
	}
}

wxBitmap PicturePaintCtrl::AsBitmap(void)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	wxPen					clsPaintPen;
	int						iWidth;
	int						iHeight;

	/*----------------------------------*/
	/* Initialize						*/
	/*----------------------------------*/
	GetPixelNumber(&iWidth, &iHeight);

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/

	ImageRasterizer clsConvert(wxSize(iWidth, iHeight));

	for(int iPosY=0; iPosY<iHeight; iPosY++)
	{
		for(int iPosX=0; iPosX<iWidth; iPosX++)
		{
			clsConvert.SetPixel(iPosX, iPosY, GetPixel(iPosX, iPosY));
		}
	}

	return clsConvert.AsBitmap();
}

bool PicturePaintCtrl::LoadBmpFile(const wxString& strPath)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	bool				bReturn = true;
	wxBitmap			clsBitmapObj;
	wxMemoryDC			clsMemDC;
	wxColour			clsPixelColour;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	do
	{
		if(false == clsBitmapObj.LoadFile(strPath, wxBITMAP_TYPE_BMP))
		{
			wxLogError("Load bitmap file failed.");
			bReturn = false;
			break;
		}

		if(false == clsBitmapObj.IsOk())
		{
			wxLogError("Bitmap data is invalid.");
			bReturn = false;
			break;
		}

		wxLogInfo("Loaded bitmap size is (%d*%d), depth is %d.", clsBitmapObj.GetWidth(), clsBitmapObj.GetHeight(), clsBitmapObj.GetDepth());
		SetPixelNumber(clsBitmapObj.GetWidth(), clsBitmapObj.GetHeight());
		FitBestSize();

		clsMemDC.SelectObject(clsBitmapObj);
		/* Paint */
		for(int iVIdx=0; iVIdx<clsBitmapObj.GetHeight(); iVIdx++)
		{
			for(int iHIdx=0; iHIdx<clsBitmapObj.GetWidth(); iHIdx++)
			{
				clsMemDC.GetPixel(iHIdx, iVIdx, &clsPixelColour);
				if(clsPixelColour == *wxBLACK)
				{
					SetPixel(iHIdx, iVIdx, 1);
				}
				else
				{
					SetPixel(iHIdx, iVIdx, 0);
				}
			}
		}

		RefreshDisplay();
	}while(0);

	return bReturn;
}

void PicturePaintCtrl::SetPixelNumber(int iHorizontalPixelNumber, int iVerticalPixelNumber)
{
	/*----------------------------------*/
	/* Variable Declaration				*/
	/*----------------------------------*/
	int					iOldWidth = wxLCDBase::GetHorizontalPixelNumber();
	int					iOldHeight = wxLCDBase::GetVerticalPixelNumber();
	int					iFillWidth = iHorizontalPixelNumber - iOldWidth;
	int					iFillHeight = iVerticalPixelNumber - iOldHeight;

	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	wxLCDBase::SetPixelNumber(iHorizontalPixelNumber, iVerticalPixelNumber);
	if(iFillWidth > 0)
	{
		wxLCDBase::FillRect(iOldWidth, 0, iFillWidth, iVerticalPixelNumber, m_clsPixelLColour);
	}
	if(iFillHeight > 0)
	{
		wxLCDBase::FillRect(0, iOldHeight, iOldWidth, iFillHeight, m_clsPixelLColour);
	}
}

void PicturePaintCtrl::SetPixelNumber(const wxSize& clsNewSizeInPixelUnit)
{
	/*----------------------------------*/
	/* Process							*/
	/*----------------------------------*/
	PicturePaintCtrl::SetPixelNumber(clsNewSizeInPixelUnit.GetWidth(), clsNewSizeInPixelUnit.GetHeight());
}
